# -*- mode: python -*-
###
#
# (c) 2000-2007 Wijnand Modderman <wijnand at tehmaze dot com>
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
#   * Redistributions of source code must retain the above copyright notice,
#     this list of conditions, and the following disclaimer.
#   * Redistributions in binary form must reproduce the above copyright notice,
#     this list of conditions, and the following disclaimer in the
#     documentation and/or other materials provided with the distribution.
#   * Neither the name of the author of this software nor the name of
#     contributors to this software may be used to endorse or promote products
#     derived from this software without specific prior written consent.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
###

# system imports
import sys
import os
import traceback

# DDB imports
from ddb.log import log, logException
from ddb.event import event
from ddb.access import AccessException

class messageCommands:
    def onLoad(self, e):
        log.msg('Bot loaded')

    def onMessage(self, e):
        #config = transportManager.config
        #if not config.get('general', 'prefixChar'):
        prefixChar = '!'
        if e.message.startswith(prefixChar):
            command = e.message[1:]
            if ' ' in command:
                command, args = command.split(' ', 1)
            else:
                args = ''
            command = command.lower()
            # raise new event
            event(e.transport, 'command', user=e.user, command=command, args=args, rawevent=e, target=e.target)

class commands:
    def __init__(self):
        self.register = {}
        self.aliases  = {}
        self.flags    = {}

    def _handleException(self, e, ex):
        msg = str(ex)
        try:
            tb = sys.exc_info()[2]
            d  = 1
            while tb.tb_next and d:
                tb = tb.tb_next
                d -= 1
            trace = traceback.extract_tb(tb)
            file  = os.path.basename(trace[0][0])
            line  = trace[0][1]
            msg   = 'Exception in %s[%d]: %s' % (file, line, str(ex))
            e.reply(msg)
            del tb
        finally:
            log.err(msg)

    def _onCommand(self, e):
        log.msg('Hooking command %s' % e.command, debug=True)
        e.commands = self
        e.lookups  = [e.command]
        while self.aliases.has_key(e.lookups[-1]):
            e.lookups.append(self.aliases[e.lookups[-1]])
            if len(e.lookups) > 10:
                del self.aliases[e.lookups[0]]
                raise Exception, "circular alias detected, removed"
        try:
            for module in self.register.keys():
                print 'HOOKMOD', module, e.lookups[-1]
                print 'HOOKMODDIR', self.register[module].keys()
                if self.register[module].has_key(e.lookups[-1]):
                    try:
                        log.msg('Hookings command %s with %s' % (e.command, str(e.lookups[-1])), debug=True)
                        self.register[module][e.lookups[-1]](e)
                    except Exception, ex:
                        logException(ex, e)
        except AccessException, e:
            log.msg('Access denied for %s (%s) to %s' % (e.user.identity,
                e.user.username, e.command))
        except Exception, e:
            raise e

    def _onLoadModule(self, e):
        if hasattr(e.module, 'EXPORT'):
            exports = getattr(e.module, 'EXPORT')
            for export in exports:
                if hasattr(e.module, export):
                    # add an instance of this class to the register
                    ref = getattr(e.module, export)()
                    self.register['%s.%s' % (e.name, export)] = {}
                    for x in dir(ref):
                        if not x.startswith('_'):
                            #self.hooks[x] = getattr(ref, x)
                            if x == 'ALIAS':
                                aliases = getattr(ref, x)
                                for alias in aliases.keys():
                                    self.aliases[alias] = aliases[alias]
                            else:
                                hook = getattr(ref, x)
                                if callable(hook):
                                    self.register['%s.%s' % (e.name, export)][x] = hook
                                del hook
                else:
                    log.msg('Could not find exported hook "%s" in "%s"' % (export, e.name))
        else:
            log.msg('Could not find EXPORT in "%s"' % (e.name), debug=True)
        
    def _onReloadModule(self, e):
        oldModuleName = str(e.oldModule.__name__)
        # scan the register for references to this module and remove them
        for module in self.register.keys():
            if module.startswith(oldModuleName):
                del self.register[module]
        self._onLoadModule(e)

    def doc(self, command):
        command = command.lower()
        docs    = []
        for module in self.register.keys():
            if self.register[module].has_key(command):
                hook = self.register[module][command]
                if hasattr(hook, '__doc__'):
                    docs.append(getattr(hook, '__doc__'))
                del hook
        return docs

# instances
command = commands()
mc      = messageCommands()

# exports
bind = (
    ['load',         mc.onLoad,               99],
    ['loadModule',   command._onLoadModule,   99],
    ['reloadModule', command._onReloadModule, 99],
    ['command',      command._onCommand,      99],
    ['message',      mc.onMessage,            80],
    )

# vim:ts=4:sw=4:et:
